// ------------------------------------------
// T.Mock
// ------------------------------------------


T.Mock = function( )
{
	this.adaptees = [ ];
};

T.Mock.prototype = 
{
	disable: function( adaptee )
	{
		function loop( value, name, adaptee )
		{
			if( name == "__placeholder" ) { return; }
			
			adaptee.__placeholder[ name ] = value;
			
			if( Lang.isFunction( value ) ) { adaptee[ name ] = T.Mock.DisabledMethod( name ); }
			else { delete adaptee[ name ]; }
		};
		
		this.adaptees.push( adaptee );
		adaptee.__placeholder = adaptee.__placeholder || { };
		
		Object.each( adaptee, loop );
	},
	
	expect: function( adaptee, config )
	{
		 if( !config.method ) { return; };
		
		var builder = new T.Mock.ExpectationBuilder( this, adaptee, config );
		 if( !adaptee.__expectations ) { builder.setupAdaptee( ); }
		 
		 builder.saveExisting( );
		 builder.addExpectation( );
	},
	
	expectationArguments: function( name, args )
	{
		function loop( arg, i, array )
		{
			  if ( !( array[ i ] instanceof Mock.Value ) )
			  {
                    array[ i ] = Mock.Value( Assert.same, [ arg ], "Argument " + i + " of " + name + "( ) is incorrect." );
               }
		};
		
		Array.each( args, loop );
		return args;
	},
	
	verifyAll: function( )
	{
		function loop( adaptee ) { this.verify( adaptee ); }
		Array.each( this.adaptees, loop, this );
	},

	verify: function( adaptee )
	{
		function loop( expectation ) 
		{
			Assert.areEqual( expectation.calls, expectation.actualCalls, "Method " + expectation.method + "( ) wasn't called the expected number of times.");
		};
		
		try { Array.each( adaptee.__expectations, loop ); } 
		catch ( err ) { Test.Runner._handleError( err ); }
		
		this.restore( adaptee );
	},
	
	restoreAll: function( )
	{
		var len, i;
		for( i = 0, len = this.adaptees.length; i < len; i++ ) { this.restore( this.adaptees[ i ] ); }
	},
	
	restore: function( adaptee )
	{
		if( !adaptee || !adaptee.__placeholder ) { this.adaptees.erase( adaptee ); return; }

		for( var fName in adaptee.__placeholder ) 
		{
			if( adaptee.__placeholder[ fName ] !== T.Mock.StubMethod ) { adaptee[ fName ] = adaptee.__placeholder[ fName ]; } 
		}
		
		delete adaptee.__expectations;
		delete adaptee.__placeholder;
		
		//TODO remove depedency!
		// Albo add declaration??
		this.adaptees.erase( adaptee );
	}
};

T.Mock = new T.Mock( );